﻿using System;
using System.Linq;
using Game1942.Library.Background.Bodies;

namespace Game1942.Library.Background
{

    public sealed class Background
    {
        private ReferencePoint[,] matrix;
        private Point dimension;
        private static Background instance;

        private Background()
        {
            matrix = new ReferencePoint[Constants.Screen.Width, Constants.Screen.Height];
            dimension = new Point(Constants.Screen.Width, Constants.Screen.Height);
        }

        public static Background Instance
        {
            get { return instance ?? (instance = new Background()); }
        }

        public ReferencePoint[,] Matrix
        {
            get { return matrix; }
        }

        public void SetDimension(int xAxis, int yAxis)
        {
            if (xAxis <= 0)
                throw new ArgumentOutOfRangeException("xAxis","The Background xAxis coordinate must be positive");
            if (yAxis <= 0)
                throw new ArgumentOutOfRangeException("yAxis","The Background yAxis coordinate must be positive");
            matrix = new ReferencePoint[xAxis, yAxis];
            dimension = new Point(xAxis,yAxis);
        }
        
        // Delete if unused
        public Point GetDimension()
        {
            return dimension;
        }
        
        public void PutPoint(ReferencePoint refPoint)
        {
            if ((object) refPoint == null)
                throw new NullReferenceException("The Point you want to Assign is null");
            if (!(refPoint >= (new Point(0,0))) || !(refPoint < dimension ))
                throw new ArgumentOutOfRangeException();
            if ((object)matrix[refPoint.X,refPoint.Y] != null)
                throw new InvalidOperationException("The Point you want to assign in the Background is already assigned");
            matrix[refPoint.X, refPoint.Y] = refPoint;
        }

        public Element GetIntruder(Body body)
        {
            return (from point in body.GetBody() where ((object) matrix[point.X, point.Y] != null)
                    select matrix[point.X, point.Y].Owner).FirstOrDefault();
        }

        public bool IsNullAt(Point point)
        {
            if (!point.BelongsTo(this))
            {
                throw new ArgumentOutOfRangeException();
            }
            return ReferenceEquals(Matrix[point.X, point.Y],null);
        }

        public static void Clear()
        {
            instance = null;
        }
    }
}
